package com.spi.xxjob;


import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class TestJob1 {

    @Autowired
    private RedissonClient redissonClient ;

    //@Scheduled代理的定时任务默认同一时刻只有一个核心线程执行，
    // 如果有两个相同时间触发的批处理，则会串行执行，可能对业务产生影响，故须加入异步注解实现多线程执行
    @Async("JobServiceExecutor")
    //@Scheduled(cron = "0/5 * * * * ? ")
    public void test01() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.info(sdf.format(new Date()) + "即将获取锁。。。" + Thread.currentThread().getName());
        RLock jobLock = redissonClient.getLock("abc");
        log.info("尝试获取锁。。。" + jobLock);
        try {
            //参数1：获取锁失败等待重试最大时间 参数2：锁自动释放时间 参数3：时间单位
            //参数1建议设置为0，批处理场景下不要等待重试，否则可能会影响该任务的下一次执行时间
            boolean flag = jobLock.tryLock(0,10000, TimeUnit.SECONDS);
            if (flag){
                log.info(sdf.format(new Date()) + "获取锁执行任务。。。" + Thread.currentThread().getName());
                Thread.sleep(7000);
            }else {
                log.error(Thread.currentThread().getName() + "获取锁失败。。。");
            }
        }catch (Exception e){
            log.error("批处理异常。。。" + e.getMessage());
        }finally {
            //因加入了异步注解，可能会有多个线程进来，造成未获取到锁的线程却要释放锁，从而抛异常
            //以线程为维度进行判定是否有权限释放锁
            if (jobLock.isLocked() && jobLock.isHeldByCurrentThread()){
                jobLock.unlock();
            }
        }

    }
}
